package main

import (
	_ "github.com/go-sql-driver/mysql" // 导入 MySQL 驱动
	"github.com/jinzhu/gorm"
)

func main() {
	// 用户名：密码@tcp(ip:port)/数据库?charset=utf8&parseTime=True&loc=Local
	db, err := gorm.Open("mysql", "root:123456@tcp(localhost:3306)/gorm_project?charset=utf8&parseTime=True&loc=Local")
	if err != nil {
		panic(err)
	}

	defer db.Close() // 关闭空闲的连接

	// First: 按照主键顺序的第一条记录， (主键升序)
	//var user models.User
	//result := db.First(&user)
	//fmt.Printf("%+T  \n", user)    // models.User
	//fmt.Print("  =====> \t", user) // {1 Jackson 235 北京 /static/upload/pic111.jpg 1586421032}
	//fmt.Printf("\n %+T ", result)  //  *gorm.DB
	//fmt.Println(result)            // &{{{0 0} 0 0 {{} 0} {{} 0}} 0xc000214000 <nil> 1 0xc000026820 false 0 {0xc00017f7d0} 0xc000218000 {{0 0} {[] {} 0xc000208050} map[] 0} 0xc0000268f0 <nil> 0xc000216000 false <nil>}

	// FirstOrCreate
	// 未找到 user，则根据给定条件创建一条新记录
	//var user models.User
	////db.FirstOrCreate(&user, models.User{Name: "wusir"})
	////db.Where(models.User{Name: "egon"}).FirstOrCreate(&user)
	//db.FirstOrCreate(&user, models.User{Name: "Jackson"})
	//fmt.Println(user)

	// 获取最后一条记录(主键降序)
	//var user models.User
	//// 按照主键顺序的最后一条记录
	//db.Last(&user) // sql 语句： select * from users order by id desc limit 1;
	//fmt.Println(user)

	// Take : 获取一条记录，没有指定排序字段
	//var user models.User
	//db.Take(&user) // sql:    select * from users limit 1;
	//fmt.Println(user)

	// Find
	//var user models.User
	// 所有记录
	//i := rand.Intn(3)  ; // db.Find(&user, i+1)
	//db.Find(&user, []int{1, 2, 3}) // sql: select * from users where id in(1,2,3);
	//result := db.Find(&user) // sql: select * from user;
	//fmt.Println(user)        // 默认是最后一个 数据
	//fmt.Println(result)      //  地址  *gorm.DB

	// 根据指定条件进行查询
	//db.Find(&user, "name = ? ", "wusir")

	//结合 where
	//db.Where("name = ? ", "alex").Find(&user) // 自动处理大小写  {2 Alex 435 上海 /static/upload/c51vbag.jpg 14798563521}
	//db.Where("name = ? ", "Alex").Find(&user) // 自动处理大小写 {2 Alex 435 上海 /static/upload/c51vbag.jpg 14798563521}
	//fmt.Println(user)

	//db.Where("name LIKE ? ", "%ac%").Find(&user) // {1 Jackson 235 北京 /static/upload/pic111.jpg 16535211035}
	//db.Where("name LIKE ? ", "%a%").Find(&user) // {2 Alex 435 上海 /static/upload/c51vbag.jpg 14798563521}
	//fmt.Printf("%+T \n", user)                  //    type ===> models.User
	//fmt.Println(user)

	// Where
	// 根据条件查询到满足条件的第一条记录
	//db.Where("phone = ? ", "18316435236").Find(&user) //{4 egon 98 深圳 sad15e4rgt.png 18316435236}
	//fmt.Println(user)

	//var user []models.User
	// 根据条件查询到满足条件的所有记录
	//db.Debug().Where("addr = ?", "深圳").Find(&user) // sql: select * from user where (addr = '深圳')

	//db.Debug().Where("phone like ?", "%21%").Find(&user) // select * from user where (phone like '%2%')

	// 结构体条件查询
	//db.Debug().Where(&models.User{Name: "Jackson", Age: 235, Addr: "北京"}).Find(&user) //  SELECT * FROM `formal_user`  WHERE (`formal_user`.`name` = 'Jackson') AND (`formal_user`.`age` = 235) AND (`formal_user`.`addr` = '北京')

	// 条件   IN   AND   Time  BETWEEN
	//db.Debug().Where("addr IN (?) ", []string{"北京", "成都"}).Find(&user)  // SELECT * FROM `formal_user`  WHERE (addr IN ('北京','成都') )
	//db.Debug().Where("addr IN (?) ", []string{"北京", "成都"}).First(&user) //  SELECT * FROM `formal_user`  WHERE (addr IN ('北京','成都') ) ORDER BY `formal_user`.`id` ASC LIMIT 1
	//fmt.Println(user)

	// Select   指定要从数据库检索的字段，默认情况下，将选择所有字段
	//db.Select("name, age").Find(&user) //select name,age from user
	//fmt.Println(user)
	//
	//db.Table("formal_user").Select("COALESCE(age,?)", 980).Rows() // COALESCE:聚合
	//// SELECT COALESCE(age,'42') FROM users;
	//fmt.Println(user)

	//Create
	//user := models.User{Name: "张三", Age: 53, Addr: "天津", Pic: "xzclvkjwte.jpg", Phone: 18266548852}
	//result := db.Debug().Create(&user)
	//fmt.Println(result)
	// 暂不支持批量插入

	// Save
	//var user models.User
	//db.Debug().First(&user, 8) // SELECT * FROM `formal_user`  WHERE (`formal_user`.`id` = 8) ORDER BY `formal_user`.`id` ASC LIMIT 1
	//// 如果 First中 默认的字段有  数据   则为更新   例如： SELECT * FROM `formal_user`  WHERE (`formal_user`.`id` = 8) ORDER BY `formal_user`.`id` ASC LIMIT 1
	//user.Name = "李四"
	//user.Age = 34
	//user.Addr = "海南"
	//user.Phone = 16530212015
	//db.Debug().Save(&user) // INSERT INTO `formal_user` (`name`,`age`,`addr`,`pic`,`phone`) VALUES ('李四',34,'','',0)
	//fmt.Println(user)

	// update
	//var user []models.User
	////db.Debug().Where("name = ?", "阿呆").Find(&user).Update("name", "阿强") // 单条数据
	////fmt.Println(user)
	//db.Debug().Where("name = ?", "阿强").Find(&user).Updates(models.User{
	//	Name:  "apple",
	//	Age:   56,
	//	Addr:  "上海",
	//	Phone: 19864130235,
	//}) // 多条数据     // UPDATE `formal_user` SET `addr` = '上海', `age` = 56, `name` = 'apple', `phone` = 19864130235  WHERE (name = ' 阿强')
	//fmt.Println(user)

	//delete
	//var user models.User
	//db.Debug().Delete(&user, 10) //  DELETE FROM `formal_user`  WHERE (`formal_user`.`id` = 10)
	//fmt.Println(user)
	// 批量删除
	//db.Where("age = ?", 20).Delete(&User{})

	// Unscoped:软删除 -> 就是逻辑删除，  gorm.Model 将DeletedAt 字段设置为时间      需要再 模型中指定
	// 查询时会忽略软删除的记录        select * from xxx where xxx = xxx  AND deleted_at IS NULL
	// 查询逻辑删除的数据  db.Unscoped().Where("xxx = ?").Find(&xxx)   // select * from xxx Where xxx = xxx;
	// 想要物理删除     db.Unscoped().Delete(&xxx)

	// Not
	//var user models.User
	//db.Debug().Not(models.User{Name: "Jackson", Age: 235}).First(&user) //  SELECT * FROM `formal_user`  WHERE (`formal_user`.`name` <> 'Jackson') AND (`formal_user`.`age` <> 235) ORDER BY `formal_user`.`id` ASC LIMIT 1
	//fmt.Println(user)

	// Or
	//var user models.User
	//db.Debug().Where("name = 'egon'").Or(models.User{Name: "alex", Age: 435}).Find(&user) //  SELECT * FROM `formal_user`  WHERE (name = 'egon') OR (`formal_user`.`name` = 'alex') AND (`formal_user`.`age` = 435)
	//fmt.Println(user)

	// Order
	//var user []models.User
	//// SELECT * FROM `formal_user`   ORDER BY age desc
	//db.Debug().Order("age desc").Find(&user) // 注意：这里的order要在find前面，否则不生效
	//fmt.Println(user)                        // 默认是 asc

	// Limit: 指定获取记录的最大数量
	// Offset: 指定在开始返回记录之前要跳过的记录数量
	//var user []models.User
	//db.Debug().Limit(5).Find(&user) // 3条     SELECT * FROM `formal_user`   LIMIT 5
	//fmt.Println(user)
	//db.Debug().Limit(10).Offset(5).Find(&user) // 从5开始10条数据  SELECT * FROM `formal_user`   LIMIT 10 OFFSET 5
	//fmt.Println(user)

	// Scan: 将结果扫描到另一个结构中
	//type Result struct {
	//	Id int
	//}
	//var user models.User
	//var result []Result
	//db.Debug().Select("id").Where("id IN (?)", []int{1, 2, 3}).Find(&user).Scan(&result)
	//fmt.Println(user)
	//fmt.Println(result)

	//Count: 获取模型的记录数
	//db.Where("name = ?", "hallen").Find(&user).Count(&count)
	// SELECT count(*) FROM users WHERE name = 'jinzhu'

	//db.Model(&User{}).Where("name = ?", "jinzhu").Count(&count)
	// SELECT count(*) FROM users WHERE name = 'jinzhu'; (count)

	// Group & Having
	// GROUP BY语句用来与聚合函数(aggregate functions such as COUNT, SUM, AVG, MIN, or MAX.)联合使用，只返回一个单个值
	// HAVING语句通常与GROUP BY语句联合使用，用来过滤由GROUP BY语句返回的记录集。
	// HAVING语句的存在弥补了WHERE关键字不能与聚合函数联合使用的不足
	//type result struct {
	//	Data  time.Time
	//	Total int
	//}
	//db.Select("name, count(*)").Group("name").Find(&result)
	//fmt.Println(result)
	// select name,count(*) FROM users GROUP BY `age` 后面不能用where限制条件，只能使用having
	// select name,count(age) FROM users GROUP BY `age` HAVING addr='xxx'

	// Distinct: 暂无
	//db.Distinct("name", "age").Order("name, age desc").Find(&results)

	// Join
	/*
	 left join ... on ..
	 right join... on ..
	*/
	// 高级查询
	// FirstOrInit & Attrs
	//FirstOrInit：获取第一个匹配的记录，或者使用给定的条件初始化一个新的记录（仅适用于struct，map条件）
	// Attrs: 如果没有找到记录，则使用Attrs中的数据来初始化一条记录：
	//var user models.User
	//// 查不到该条记录，则使用attrs值替换， 查到记录，则使用数据库中的值    ***他只是查找
	//db.Debug().Where(models.User{Name: "hallen"}).Attrs(models.User{Name: "hallen", Age: 16}).FirstOrInit(&user) // SELECT * FROM `formal_user`  WHERE (`formal_user`.`name` = 'hallen') ORDER BY `formal_user`.`id` ASC LIMIT 1
	//fmt.Println(user)

	/*  FirstOrInit & Assign
	Assign:不管是否找的到，最终返回结构中都将带上Assign指定的参数，有则代替，没有则添加
	*/
	//var user models.User
	//// 不管是否找到匹配对应记录，使用Assign值替代查询到的值
	//db.Debug().Where("id = ? ", "9").Assign(models.User{Id: 10}).FirstOrInit(&user) //  SELECT * FROM `formal_user`  WHERE (id = '9' ) ORDER BY `formal_user`.`id` ASC LIMIT 1
	//// {10 apple 56 上海 798cv4d6a5fg4we98t.jpg 19864130235}
	//fmt.Println(user)

	// Pluck
	// 用于从数据库查询单个列，并将结果扫描到切片，如果想要查找多列，应该使用Select  和  Scan
	//var user models.User
	//var age []int64
	//db.Debug().Find(&user).Pluck("age", &age) // SELECT * FROM `formal_user`   ------------   SELECT age FROM `formal_user`  WHERE `formal_user`.`id` = 9
	//fmt.Println(user)                         // SELECT age FROM `formal_user`  WHERE `formal_user`.`id` = 9
	//fmt.Println(age)                          // [56]
	//
	//var names []string
	//db.Model(&models.User{}).Pluck("name", &names)
	//fmt.Println(user)
	// 超过一列的查询，应该使用 `Scan` 或者 `Find`，例如：
	//db.Select("name", "age").Scan(&users)
	//db.Select("name", "age").Find(&users)

	//Scopes: Scopes 允许你指定常用的查询，可以在调用方法时引用这些查询

	// LogMode :
	/*
		 Gorm 有内置的日子记录器，默认情况下，它会打印发生的错误
		 启动Logger，显示详细日志
		db.LogMode(true)
		 也可以查看单语句的信息
		db.Debug().Where("name = ?", "hallen").First(&user{})
	*/
}
